"""
具体AST节点实现

定义各种具体的AST节点类型。
"""

from typing import Any, Dict, List, Optional, Union
from pathlib import Path
from .base import Ast, AstNode, CompositeAst, AstNodeType, AstContext

# 前向声明，避免循环导入
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from ..visitor import AstVisitor


# ============================================================================
# 基础控制节点
# ============================================================================

class Sequence(CompositeAst):
    """顺序执行节点 - 按顺序执行所有子节点"""
    
    @property
    def node_type(self) -> AstNodeType:
        return AstNodeType.SEQUENCE
    
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        return visitor.visit_sequence(self, context)


class Parallel(CompositeAst):
    """并行执行节点 - 并行执行所有子节点"""
    
    def __init__(self, max_workers: int = 4, **kwargs):
        super().__init__(**kwargs)
        self.max_workers = max_workers
    
    @property
    def node_type(self) -> AstNodeType:
        return AstNodeType.PARALLEL
    
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        return visitor.visit_parallel(self, context)


class Conditional(CompositeAst):
    """条件执行节点 - 根据条件执行不同分支"""
    
    def __init__(
        self,
        condition: str,
        true_branch: Optional[Ast] = None,
        false_branch: Optional[Ast] = None,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.condition = condition
        self.true_branch = true_branch
        self.false_branch = false_branch
        
        # 将分支添加到子节点列表
        if true_branch:
            self.children.append(true_branch)
        if false_branch:
            self.children.append(false_branch)
    
    @property
    def node_type(self) -> AstNodeType:
        return AstNodeType.CONDITIONAL
    
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        return visitor.visit_conditional(self, context)


class Loop(CompositeAst):
    """循环执行节点 - 重复执行子节点"""
    
    def __init__(
        self,
        condition: Optional[str] = None,
        max_iterations: Optional[int] = None,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.condition = condition
        self.max_iterations = max_iterations
    
    @property
    def node_type(self) -> AstNodeType:
        return AstNodeType.LOOP
    
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        return visitor.visit_loop(self, context)


# ============================================================================
# 视频处理节点
# ============================================================================

class FfmpegSlice(AstNode):
    """FFmpeg视频切片节点"""
    
    def __init__(
        self,
        input_path: Optional[str] = None,
        output_path: Optional[str] = None,
        max_duration: int = 30,
        min_duration: int = 3,
        scene_detection: bool = True,
        quality: str = "medium",
        filters: Optional[List[str]] = None,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.input_path = input_path
        self.output_path = output_path
        self.max_duration = max_duration
        self.min_duration = min_duration
        self.scene_detection = scene_detection
        self.quality = quality
        self.filters = filters or []
    
    @property
    def node_type(self) -> AstNodeType:
        return AstNodeType.FFMPEG_SLICE
    
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        return visitor.visit_ffmpeg_slice(self, context)
    
    def validate(self) -> List[str]:
        errors = super().validate()
        
        if self.max_duration <= 0:
            errors.append("最大时长必须大于0")
        
        if self.min_duration <= 0:
            errors.append("最小时长必须大于0")
        
        if self.min_duration >= self.max_duration:
            errors.append("最小时长必须小于最大时长")
        
        if self.quality not in ["low", "medium", "high"]:
            errors.append("质量参数必须是 low, medium, high 之一")
        
        return errors


class ExtractMetadata(AstNode):
    """提取视频元数据节点"""
    
    def __init__(
        self,
        input_path: Optional[str] = None,
        include_thumbnails: bool = False,
        thumbnail_count: int = 3,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.input_path = input_path
        self.include_thumbnails = include_thumbnails
        self.thumbnail_count = thumbnail_count
    
    @property
    def node_type(self) -> AstNodeType:
        return AstNodeType.EXTRACT_METADATA
    
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        return visitor.visit_extract_metadata(self, context)


class ScanDirectory(AstNode):
    """扫描目录节点"""
    
    def __init__(
        self,
        path: str,
        extensions: Optional[List[str]] = None,
        recursive: bool = True,
        pattern: Optional[str] = None,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.path = path
        self.extensions = extensions or [".mp4", ".avi", ".mov", ".mkv"]
        self.recursive = recursive
        self.pattern = pattern
    
    @property
    def node_type(self) -> AstNodeType:
        return AstNodeType.SCAN_DIRECTORY
    
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        return visitor.visit_scan_directory(self, context)
    
    def validate(self) -> List[str]:
        errors = super().validate()
        
        if not self.path:
            errors.append("扫描路径不能为空")
        
        if not Path(self.path).exists():
            errors.append(f"扫描路径不存在: {self.path}")
        
        return errors


# ============================================================================
# AI分类节点
# ============================================================================

class GeminiClassify(AstNode):
    """Gemini AI分类节点"""
    
    def __init__(
        self,
        input_path: Optional[str] = None,
        categories: Optional[List[str]] = None,
        model: str = "gemini-pro-vision",
        temperature: float = 0.1,
        confidence_threshold: float = 0.8,
        max_tokens: int = 1000,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.input_path = input_path
        self.categories = categories or ["AI素材", "产品展示", "产品使用", "模特试穿"]
        self.model = model
        self.temperature = temperature
        self.confidence_threshold = confidence_threshold
        self.max_tokens = max_tokens
    
    @property
    def node_type(self) -> AstNodeType:
        return AstNodeType.GEMINI_CLASSIFY
    
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        return visitor.visit_gemini_classify(self, context)
    
    def validate(self) -> List[str]:
        errors = super().validate()
        
        if not self.categories:
            errors.append("分类类别不能为空")
        
        if not 0 <= self.temperature <= 1:
            errors.append("temperature必须在0-1之间")
        
        if not 0 <= self.confidence_threshold <= 1:
            errors.append("置信度阈值必须在0-1之间")
        
        return errors


# ============================================================================
# 输出节点
# ============================================================================

class OutputDraft(AstNode):
    """输出剪映草稿节点"""
    
    def __init__(
        self,
        template_path: Optional[str] = None,
        output_path: Optional[str] = None,
        project_name: Optional[str] = None,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.template_path = template_path
        self.output_path = output_path
        self.project_name = project_name
    
    @property
    def node_type(self) -> AstNodeType:
        return AstNodeType.OUTPUT_DRAFT
    
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        return visitor.visit_output_draft(self, context)


class OrganizeFiles(AstNode):
    """文件整理节点"""
    
    def __init__(
        self,
        base_path: str,
        structure: str = "{category}/{date}/{filename}",
        create_subdirs: bool = True,
        move_files: bool = True,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.base_path = base_path
        self.structure = structure
        self.create_subdirs = create_subdirs
        self.move_files = move_files
    
    @property
    def node_type(self) -> AstNodeType:
        return AstNodeType.ORGANIZE_FILES
    
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        return visitor.visit_organize_files(self, context)


class GenerateReport(AstNode):
    """生成报告节点"""
    
    def __init__(
        self,
        output_path: Optional[str] = None,
        format: str = "json",
        include_statistics: bool = True,
        include_thumbnails: bool = False,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.output_path = output_path
        self.format = format
        self.include_statistics = include_statistics
        self.include_thumbnails = include_thumbnails
    
    @property
    def node_type(self) -> AstNodeType:
        return AstNodeType.GENERATE_REPORT
    
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        return visitor.visit_generate_report(self, context)
    
    def validate(self) -> List[str]:
        errors = super().validate()
        
        if self.format not in ["json", "html", "csv", "xml"]:
            errors.append("报告格式必须是 json, html, csv, xml 之一")
        
        return errors


# ============================================================================
# 工具节点
# ============================================================================

class FileOperation(AstNode):
    """文件操作节点"""
    
    def __init__(
        self,
        operation: str,
        source_path: Optional[str] = None,
        target_path: Optional[str] = None,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.operation = operation  # copy, move, delete, rename
        self.source_path = source_path
        self.target_path = target_path
    
    @property
    def node_type(self) -> AstNodeType:
        return AstNodeType.FILE_OPERATION
    
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        return visitor.visit_file_operation(self, context)
    
    def validate(self) -> List[str]:
        errors = super().validate()
        
        valid_operations = ["copy", "move", "delete", "rename"]
        if self.operation not in valid_operations:
            errors.append(f"操作类型必须是 {valid_operations} 之一")
        
        if self.operation != "delete" and not self.source_path:
            errors.append("源路径不能为空")
        
        if self.operation in ["copy", "move", "rename"] and not self.target_path:
            errors.append("目标路径不能为空")
        
        return errors


class DataTransform(AstNode):
    """数据转换节点"""
    
    def __init__(
        self,
        transform_type: str,
        input_data: Optional[Any] = None,
        transform_config: Optional[Dict[str, Any]] = None,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.transform_type = transform_type
        self.input_data = input_data
        self.transform_config = transform_config or {}
    
    @property
    def node_type(self) -> AstNodeType:
        return AstNodeType.DATA_TRANSFORM
    
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        return visitor.visit_data_transform(self, context)
